Developer Documentation

QuickTime 4 API Documentation

QuickTime 4 Reference

| Previous | Chapter Contents | Chapter Top | Next |

Handling Multiple Formats

Although you can write separate versions of your effect algorithm for each combination of bit depth and pixel format, Apple recommends that you implement your effect algorithm once for each bit depth. You should then use the Apple-supplied blit macros to automatically generate versions of these implementations for each supported pixel format. This significantly reduces the number of separate implementations you have to maintain, and allows easy support of multiple pixel formats.

The blit macros are contained in the file BltMacros.h , which is included with the sample effect framework code.

To use the blit macros in your effect component, you must store each bit depth implementation of your effect algorithm in a separate file. These files are then included into the effect component's main source code file multiple times, once per pixel format supported. Each inclusion is surrounded by #define statements that define the pixel format version to be generated.

Each file uses a #include statement to include BltMacros.h , and all operations that read pixels from a source buffer or write pixels to the destination buffer are performed using appropriate macros.

The macros are automatically converted to the correct operations for the pixel format when the file is included into the main source code. This generates a version of the algorithm for each pixel format.

Finally, code is put into place in the effect component's EffectRenderFrame function, which calls the appropriate generated algorithm according to the current bit depth and pixel format of the source buffers.

Implementing a Bit-depth Specific Version of Your Algorithm

Listing 23 shows an example implementation of an effect algorithm. The code uses the blit macros to read pixels from the source frame and write them to the destination frame. This example shows a filter that changes a single source. It also shows how to read and alter a single pixel at a time; other effects may handle multiple pixels at a time for efficiency.

The sample shows the following operations for each pixel of the source frame:

  1. Retrieving the next pixel from the source, using the Get16 (which reads a 16-bit pixel from a memory address) and cnv16SPFto16RG (which converts a 16-bit pixel in the current pixel format to the standardized 16-bit ARGB format) macros to handle pixel format conversion;
  2. Decomposing the pixel into alpha, red, green and blue components;
  3. Reassembling the alpha, red, green and blue components into a standardized ARGB pixel value;
  4. Writing the pixel value to the destination buffer, using the cnv16RGto16DPF (which converts the 16-bit standardized format pixel back into the current buffer's 16-bit pixel format) and Set16 (which writes a 16-bit pixel to a memory address) macros to handle pixel format conversion.

The actual effect implementation, which would alter the alpha, red, green and blue values of each pixel according to the effect specification, is not shown in this example code.

Listing 23 A sample effect algorithm for 16-bit frames

#include <BltMacros.h>
void EffectFilter16(BlitGlobals *glob);
void EffectFilter16(BlitGlobals *glob)
{
    long    height = glob->height;      // Local copy of the height of
                                        // the buffers
    UInt16  *srcA = glob->sources[0].srcBaseAddr;   // Local pointer to
                                                // the first source image
    UInt16  *dst = glob->dstBaseAddr;   // Local pointer to the
                                        // destination
    long    srcABump;
    long    dstBump;
    
    // Work out the source and destination "bumps". The rowBytes value
    // gives you the number of bytes in each scanline of an image. This
    // is not necessarily the same as the number of pixels in a scanline
    // multiplied by the number of bytes each pixel occupies. When
    // we copy pixels from source to destination, via our effect
    // algorithm, we need to account for this discrepancy. The following
    // lines lines pre-calculate the differences.
    srcABump = glob->sources[0].srcRowBytes - (glob->width * 2);
    dstBump = glob->dstRowBytes - (glob->width * 2);

    // Now, for every scanline in the source image we are dealing with...
    while (height--)
    {
        long    width = glob->width;

        // ...iterate through every pixel in that scanline
        while (width--)
        {
            UInt16      thePixelValue;

            // Retrieve the next pixel value
            thePixelValue = Get16(srcA);
            srcA++;

            // Call to blit macros to ensure the pixel format is
            // converted appropriately
            cnv16SPFto16RG(thePixelValue);

            // Get the alpha, red, green and blue values of the pixel
            alpha = 0x8000 & thePixelValue;
            red = (thePixelValue & 0x7C00) >> 10;
            green = (thePixelValue & 0x03E0) >> 5;
            blue = (thePixelValue & 0x001F) >> 0;

            // IMPLEMENT YOUR EFFECT ALGORITHM HERE ON EACH PIXEL

            // Re-assemble the A, R, G and B values into a 16-bit
            // destination pixel
            thePixelValue = alpha | (red << 10) | (green << 5)
                                  | (blue << 0));

            // Set the destination pixel,first passing it through the
            // appropriate blit macro to
            // ensure the correct pixel format conversion is performed
            cnv16RGto16DPF(thePixelValue);
            Set16(dst, thePixelValue);
            dst++;
        }

        // Bump the source and destination pointers we are using, to
        // avoid problems when moving from one scanline to the next
        srcA = (void *) (((Ptr) srcA) + srcABump);
        dst = (void *) (((Ptr) dst) + dstBump);
    }
}

Including the Bit-depth Implementations into Your Effect Code

Once you have produced separate implementations of your effect algorithm for each bit depth you support, you need to include these into your main effect source code file. Each bit depth implementation is included once for every pixel format you support.

Listing 24 shows statements to include the 16-bit implementation of the effect into the main effect source code file. The implementation is included three times, for the following pixel formats:

  1. Big-endian 555 RGB
  2. Little-endian 555 RGB
  3. Little-endian 565 RGB

The result of the code in Listing 24 is that your effect source code contains three separate versions of the effect algorithm for handling 16-bit sources. These are named EffectFilter16BE555 , EffectFilter16LE555 and EffectFilter16LE565, respectively.

Listing 24 Including the 16-bit implementation into the main effect source code

// 16-bit, Big Endian 555 pixel format
#define EffectFilter16 EffectFilter16BE555
#define srcIs16BE555 1
#define dstIs16BE555 1
#include "EffectFilter16.c"
#undef EffectFilter16
#undef srcIs16BE555
#undef dstIs16BE555

// 16-bit, Little Endian, 555 pixel format
#define EffectFilter16 EffectFilter16LE555
#define srcIs16LE555 1
#define dstIs16LE555 1
#include "EffectFilter16.c"
#undef EffectFilter16
#undef srcIs16LE555
#undef dstIs16LE555

// 16-bit, Little Endian, 565 pixel format
#define EffectFilter16 EffectFilter16LE565
#define srcIs16LE565 1
#define dstIs16LE565 1
#include "EffectFilter16.c"
#undef EffectFilter16
#undef srcIs16LE565
#undef dstIs16LE565

Calling the Effect Implementations from EffectRenderFrame

Finally, you must provide code inside your EffectRenderFrame function to call the appropriate implementation of your effect algorithm, depending on the pixel format and bit depth of the source frames you are dealing with. Listing 25 shows how to do this for the 16-bit pixel formats.

Listing 25 Calling pixel format specific versions of the 16-bit effect implementation

switch (glob->dstPixelFormat)
{
    case k16BE555PixelFormat:
            EffectFilter16BE555(glob);
            break;
    case k16LE565PixelFormat:
            EffectFilter16LE565(glob);
            break;
    case k16LE555PixelFormat:
            EffectFilter16LE555(glob);
            break;
}

The code to handle the 32-bit pixel formats is an easy extension of the code shown in this section, and can be found in the sample effect component included in the QuickTime 3 SDK and described in detail in the next section.


© 1999 Apple Computer, Inc.

| Previous | Chapter Contents | Chapter Top | Next |